package lz.controls
{
	import com.common.display.BitmapScale9Grid;
	
	import flash.display.Bitmap;
	import flash.display.DisplayObject;
	import flash.events.MouseEvent;
	import flash.events.TimerEvent;
	import flash.utils.Dictionary;
	import flash.utils.Timer;
	
	import lz.controls.core.InvalidationType;
	import lz.controls.core.UIComponent;
	import lz.controls.events.ComponentEvent;

    /**
     *BaseButton 类是所有按钮组件的基类，用于定义所有按钮的通用属性和方法。
	 * 此类将处理绘制状态以及对按钮事件的调度。
     */
	public class BaseButton extends UIComponent
	{
		/**
         * 背景
		 */
		protected var background		:DisplayObject;
		/**
         * 鼠标状态
		 */
		protected var mouseState		:String;
		/**
		 * 是否绘制9宫格背景
		 */		
		protected  var _scale9GridBg 	:Boolean = false;
		/**
		 *  绘制9宫格时顶部间隔
		 */		
		protected var scaleGridTop			:Number = 0;
		/**
		 *  绘制9宫格时底部间隔
		 */		
		protected var scaleGridBottom		:Number = 0;
		/**
		 *  绘制9宫格时左边间隔
		 */		
		protected var scaleGridLeft		:Number = 0;
		/**
		 *  绘制9宫格时右边间隔
		 */		
		protected var scaleGridRight		:Number = 0;
		/**
         * 是否选中状态
		 */
		protected var _selected		:Boolean = false;
		/**
         *是否当用户在组件上按住鼠标按键时重复调度 buttonDown 事件
		 */
		protected var _autoRepeat		:Boolean = false;
        /**
         * 鼠标按下定时器
         */
		protected var pressTimer		:Timer;
		/**
         * 鼠标是否锁定
		 */		 
		private var _mouseStateLocked	:Boolean = false;
        /**
         * 没有锁定前的鼠标状态
         */
		private var unlockedMouseState	:String;
		/**
		 *背景缓存 
		 */		
		private var cacheBgDic			:Dictionary = new Dictionary();
        /**
         *默认样式
         */
		private static var defaultStyles:Object = {upSkin:"Button_upSkin",downSkin:"Button_downSkin",overSkin:"Button_overSkin",
												  disabledSkin:"Button_disabledSkin",
												  selectedDisabledSkin:null,
												  selectedUpSkin:"Button_downSkin",selectedDownSkin:"Button_downSkin",selectedOverSkin:"Button_downSkin",
												  focusRectSkin:null, focusRectPadding:null,
												  repeatDelay:500,repeatInterval:35};
        /**
         *检索当前组件的默认样式映射。
         */
		public static function getStyleDefinition():Object { return defaultStyles; }
		/**
         *创建新的 BaseButton 实例。
		 */
		public function BaseButton() 
		{
			super();

			buttonMode = true;
			mouseChildren = false;
			useHandCursor = true;

			setupMouseEvents();
			setMouseState("up");

			pressTimer = new Timer(1,0);
			pressTimer.addEventListener(TimerEvent.TIMER,buttonDown,false,0,true);
		}
		/**
		 * 获取一个值，指示组件能否接受用户输入。
		 */
		override public function get enabled():Boolean 
		{
			return super.enabled;
		}
		/**
         *设置一个值，指示组件能否接受用户输入。
		 */
		override public function set enabled(value:Boolean):void 
		{
			super.enabled = value;
			mouseEnabled = value;
		}
		/**
		 * 获取一个布尔值，指示切换按钮是否处于选中状态。
         * @default false
		 */
		public function get selected():Boolean 
		{
			return _selected;
		}
		/**
         *设置一个布尔值，指示切换按钮是否处于选中状态。
		 */
		public function set selected(value:Boolean):void 
		{
			if (_selected == value) { return; }
			_selected = value;
			invalidate(InvalidationType.STATE);
		}
		/**
         *获取或设置一个布尔值，该值指示是否当用户在组件上按住鼠标按键时重复调度 buttonDown 事件。 
		 * true 值指示当鼠标按键保持按下状态时重复调度 buttonDown 事件；false 值指示仅调度一次该事件。
		 * 如果该值为 true，则经过由 repeatDelay 样式指定的延迟后，将对 buttonDown 事件按 repeatInterval 样式所指定的间隔进行调度。
		 * 默认值为 false。
		 */
		public function get autoRepeat():Boolean 
		{
			return _autoRepeat;
		}		
		public function set autoRepeat(value:Boolean):void
		{
			_autoRepeat = value;
		}		
		/**
         * 设置鼠标锁定状态
		 */
		public function set mouseStateLocked(value:Boolean):void 
		{
			_mouseStateLocked = value;
			if (value == false) { setMouseState(unlockedMouseState); }
			else { unlockedMouseState = mouseState; }
		}
		/**
         * 通过 ActionScript 设置鼠标状态。 
		 * BaseButton 类在内部使用此属性，但是也可对其进行手动调用，这样将直观地设置鼠标状态。
		 * 参数
		 * state:String — 指定鼠标状态的字符串。 支持的值为“up”、“over”和“down”。
		 */
		public function setMouseState(state:String):void 
		{
			if (_mouseStateLocked) { unlockedMouseState = state; return; }
			if (mouseState == state) { return; }
			mouseState = state;
			invalidate(InvalidationType.STATE);
		}
		/**
		 * 获取或设置是否九宫格绘制背景 
		 * @param value
		 */		
		public function set scale9GridBg(value:Boolean):void
		{
			_scale9GridBg = value;
		}
		public function get scale9GridBg():Boolean
		{
			return _scale9GridBg;
		}
		/**
		 *设置9宫格四边间隔 
		 * @param topGridV
		 * @param bottomGridV
		 * @param leftGridV
		 * @param rightGridV
		 * 
		 */			
		public function setGridValue(topGridV:Number,
									 bottomGridV:Number,
									 leftGridV:Number,
									 rightGridV:Number):void
		{
			scaleGridTop = topGridV;
			scaleGridBottom = bottomGridV;
			scaleGridLeft = leftGridV;
			scaleGridRight = rightGridV;
		}
		/**
         * 设置鼠标事件
		 */
		protected function setupMouseEvents():void
		{
			addEventListener(MouseEvent.ROLL_OVER,mouseEventHandler,false,0,true);
			addEventListener(MouseEvent.MOUSE_DOWN,mouseEventHandler,false,0,true);
			addEventListener(MouseEvent.MOUSE_UP,mouseEventHandler,false,0,true);
			addEventListener(MouseEvent.ROLL_OUT,mouseEventHandler,false,0,true);
		}
		/**
         * 鼠标事件捕获
		 */
		protected function mouseEventHandler(event:MouseEvent):void 
		{
			if (event.type == MouseEvent.MOUSE_DOWN)
			{
				setMouseState("down");
				startPress();
			} else if (event.type == MouseEvent.ROLL_OVER || event.type == MouseEvent.MOUSE_UP) 
			{
				setMouseState("over");
				endPress();
			} else if (event.type == MouseEvent.ROLL_OUT)
			{
				setMouseState("up");
				endPress();
			}
		}
		/**
         * 开始按下
		 */
		protected function startPress():void 
		{
			if (_autoRepeat) 
			{
				pressTimer.delay = Number(getStyleValue("repeatDelay"));
				pressTimer.start();
			}
			dispatchEvent(new ComponentEvent(ComponentEvent.BUTTON_DOWN, true));
		}
		/**
         * 鼠标按下
		 */
		protected function buttonDown(event:TimerEvent):void 
		{
			if (!_autoRepeat) { endPress(); return; }
			if (pressTimer.currentCount == 1) { pressTimer.delay = Number(getStyleValue("repeatInterval")); }
			dispatchEvent(new ComponentEvent(ComponentEvent.BUTTON_DOWN, true));
		}
		/**
         * 松开
		 */
		protected function endPress():void
		{
			pressTimer.reset();
		}
		/**
         * 绘制
		 */
		override protected function draw():void
		{
			if (isInvalid(InvalidationType.STYLES,InvalidationType.STATE)) 
			{
				drawBackground();
				invalidate(InvalidationType.SIZE,false); // invalidates size without calling draw next frame.
			}
			if (isInvalid(InvalidationType.SIZE))
			{
				drawLayout();
			}
			super.draw();
		}
		/**
         * 绘制背景
		 */
		protected function drawBackground():void
		{
			var styleName:String = (enabled) ? mouseState : "disabled";
			if (selected) { styleName = "selected"+styleName.substr(0,1).toUpperCase()+styleName.substr(1); }
			styleName += "Skin";
			var bg:DisplayObject = background;
			if(cacheBgDic[styleName] == null)
			{
				background = getDisplayObjectInstance(getStyleValue(styleName));
			}
			else
			{
				background = cacheBgDic[styleName];
			}
			if(background)
			{
				if(cacheBgDic[styleName] == null && _scale9GridBg && background is Bitmap)
				{
					background = new BitmapScale9Grid(background as Bitmap,scaleGridTop,scaleGridBottom,scaleGridLeft,scaleGridRight);
				}
				if(cacheBgDic[styleName] == null)
				{
					cacheBgDic[styleName] = background;
				}
				addChildAt(background, 0);
			}
			if (bg != null && bg != background && bg.parent) 
			{ 
				bg.parent.removeChild(bg); 
			}
		}
		/**
         * 绘制布局
		 */
		protected function drawLayout():void 
		{
			if(background)
			{
				background.width = width;
				background.height = height;
			}
		}
	}
}